/*
 * Author:  Copyright (c) 2013 Toby
 * E-Mail:  smurffit@gmail.com
 * Web:     https://code.google.com/p/chrome-mfi-filter4kiva/
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, see <http://www.gnu.org/licenses/>.
 */

'use strict';

// TODO use CSS in HTML file
// TODO show count of configured filtered/highlighted items
// TODO save last used order

/* ----- FUNC ----- */
function mfi(id, name, rating, blocked, highlight, cat, religious, social, top)
{
	this.id = id;
	this.name = name;
	this.rating = rating;
	this.blocked = blocked;
	this.highlight = highlight;
	this.cat = cat;
	this.religious = religious;
	this.social = social;
	this.top = top;
}

function mfiAa(name, religious, social)
{
	this.name = name;
	this.religious = religious;
	this.social = social;
}
/* ----- END FUNC ----- */

/* ----- VARS ----- */

/**
 * 0 = off, 1 = verbose, 2 = debug
 * @type {number}
 */
var DEBUG = 0;

var PARTNER_PAGE_URL = 'http://www.kiva.org/partners';
var AASFSHNR_LIST_URL = 'https://docs.google.com/spreadsheet/lv?key=0AhfuHQgSfgERdDhUOW9jajFUSWFiang0eXVlSGI3YVE&f=true&noheader=true&gid=5';
var regexExtractPartnerData = /<h1 class=\"name\"><a href=\"http:\/\/www\.kiva\.org\/partners\/(\d{1,6})\">(.{3,160})<\/a><\/h1>[\s\S]*<div class=\"partnerRating .{0,40}\" title=\"Partner Risk Rating:(.{1,20})\">/m;
var btnSave1 = document.getElementById('save');
var btnSave2 = document.getElementById('save2');
var txtrealHidden = document.getElementById('realHidden');
var txtcolorHidden = document.getElementById('colorHidden');
var txtcolorHighlight = document.getElementById('colorHighlight');
var chkshowRatingStars = document.getElementById('showRatingStars');
var chkstate = document.getElementById('state');
var chkautoUpdate = document.getElementById('autoUpdate');
var chkenableAa = document.getElementById('enableAa');
var partnerCount = document.getElementById('partnerCount');
var partnerLastUpdate = document.getElementById('partnerLastUpdate');
var dbdlLink = document.getElementById('dbdl');
var storage = chrome.storage.local;
var res;
var bg = chrome.extension.getBackgroundPage();
var lastSort = 0;
/* ----- END VARS ----- */

function save_options(callback)
{
	var trends_dom = document.getElementById('mfi_list').getElementsByTagName('input');
	var regExSource = [];
	var regExHighlight = [];

	for ( var i = 0, len = trends_dom.length; i < len; i++)
	{
		var id = trends_dom[i].id;
		var blocked = trends_dom[i].checked;
		var highlight = false;

		for ( var j = 0, lem = res.length; j < lem; j++)
		{
			if (id == res[j].id)
			{
				res[j].blocked = blocked;
				res[j].cat = document.getElementById(id.concat('c')).value;
				highlight = document.getElementById(id.concat('d')).checked;
				res[j].highlight = highlight;
				if (blocked)
				{
					regExSource.push(res[j].name);
				}
				else if (highlight)
				{
					regExHighlight.push(res[j].name);
				}
				break;
			}
		}
	}

	bg.saveMfiList(res, function()
	{
		bg.saveRegEx(regExSource, regExHighlight, function()
		{
			saveSettings(function()
			{
				if (res !== undefined)
				{
					lastSort = 0;
					createCheckbox(sortTable(res, 1), function()
					{
						callback();
					});
				}
				else
				{
					callback();
				}
			});
		});
	});
}

function saveSettings(callback)
{
	bg.config.colorFilteredHide = txtrealHidden.value;
	bg.config.colorFilteredShow = txtcolorHidden.value;
	bg.config.colorHighlighted = txtcolorHighlight.value;
	bg.config.showRatingStars = chkshowRatingStars.checked;
	bg.config.block = chkstate.checked;
	bg.config.autoUpdate = chkautoUpdate.checked;
	bg.config.enableAa = chkenableAa.checked;

	bg
			.saveConfig(function()
			{
				bg
						.loadConfig(function()
						{

							// Update status to let user know were saved.
							btnSave1.setAttribute('disabled', 'disabled');
							btnSave2.setAttribute('disabled', 'disabled');
							$('#status')
									.html(
											'Options Saved. Please reload all open Kiva tabs for the changes to take effect.');
							$('#status').highlight();

							setTimeout(
									function()
									{
										btnSave1.removeAttribute('disabled');
										btnSave2.removeAttribute('disabled');

										if ($('#status').text().length === 'Options Saved. Please reload all open Kiva tabs for the changes to take effect.'.length)
										{
											$('#status').html('');
										}
									}, 3000);
							callback();
						});
			});
}

// Restores form box state to saved value from localStorage.
function restore_options(callback)
{
	bg.loadMfiList(false, function(result)
	{
		lastSort = 0;
		if (result !== undefined)
		{
			res = sortTable(result, 1);
			createCheckbox(res, callback);
		}
		else if (bg.config.autoUpdate)
		{
			bg.optionsAutoClose = false; // no need to update if we rebuild anyway
			fetch(function()
			{
				//
			});
		}
	});

	txtrealHidden.value = bg.config.colorFilteredHide;
	txtcolorHidden.value = bg.config.colorFilteredShow;
	txtcolorHighlight.value = bg.config.colorHighlighted;
	chkshowRatingStars.checked = bg.config.showRatingStars;
	chkstate.checked = bg.config.block;
	chkautoUpdate.checked = bg.config.autoUpdate;
	chkenableAa.checked = bg.config.enableAa;
}

function fetchRemoteData(url, callback)
{
	// TODO notify about errors (bad gateway, timeout etc.)
	var xhr = new XMLHttpRequest();
	xhr.onreadystatechange = function()
	{
		if ((xhr.readyState == 4) && (xhr.status == 200))
		{
			callback(xhr.responseText);
		}
	};
	xhr.open('GET', url, true);
	xhr.send();
}

function fetchPartners(callback)
{
	// TODO progress indicator?
	fetchRemoteData(
			PARTNER_PAGE_URL,
			function(data)
			{
				var list = data.substring(data.indexOf('<tbody'), data.indexOf('</table>')).split(
						'<tr');
				// <div class="resultsSummary"><span class="number">184</span> Partners</div>
				var regex = /<div class=.resultsSummary.><span class=.number.>(\d{1,4})<.span> Partners<.div>/m;

				var iPartners = parseInt(regex.exec(data)[1], 10);
				res = extractData(list, iPartners);
				var d = new Date();
				bg.mfiUpdateTimeStamp = d.getTime();
				console.log('Fetched partner list: ' + iPartners);
				if (bg.config.enableAa)
				{
					fetchAaData(function()
					{
						callback();
					});
				}
				else
				{
					callback();
				}
			});
}

function fetchAaData(callback)
{
	fetchRemoteData(AASFSHNR_LIST_URL, function(data)
	{
		var list = data.substring(data.indexOf('tblMain'), data.indexOf('footer')).split('rowNum');
		var re = extractAaData(list);
		console.log('\n\nFetched AASFSHNR MFI ratings: ' + list.length);
		linkAaToMfi(re);
		callback();
	});
}

function linkAaToMfi(AaData)
{
	var tmpName = "";
	var k = AaData.length;
	var iRel = 0;
	var iSoc = 0;
	var iTop = 0;

	for ( var i = 0, l = res.length; i < l; i++)
	{
		tmpName = res[i].name;

		for ( var j = 0; j < k; j++)
		{
			if (AaData[j].name === tmpName)
			{
				// because type-safety is for n00bs...
				iRel = parseInt(AaData[j].religious, 10);
				iSoc = parseInt(AaData[j].social, 10);

				if (iRel == 4 && iSoc >= 3)
				{
					iTop = 4;
				}
				else if (iRel >= 3)
				{
					iTop = 3;
				}
				else if ((iRel == 1) || (iRel <= 2 && iRel > 0 && iSoc <= 2))
				{
					iTop = 1;
				}
				else
				{
					iTop = 2;
				}

				res[i].religious = iRel;
				res[i].social = iSoc;
				res[i].top = iTop;
				break;
			}
		}
	}
	save_options(function()
	{
		// 
	});
}

function extractAaData(list)
{
	// mfiAa(name, religious, social)
	var re = [];
	var regex = /(\d{1})<td.{10,36}>(\d{1})<td.{10,36}>([^<]{3,160})<td/m;
	for ( var i = 6, len = list.length; i < len; i++)
	{
		var results = regex.exec(list[i].substring(list[i].indexOf('s5') + 4));
		if (results)
		{
			re[i - 6] = new mfiAa(results[3].replace('&amp;', '&'), results[1], results[2]);
		}
		else
		{
			console.log(i);
		}
	}
	return re;
}

function extractData(list, iPartners)
{
	// mfi(id, name, rating, blocked, highlight, cat, religious, social, top)
	var resultRating, re = [];

	for ( var i = 1, len = list.length; i < len; i++)
	{
		var results = regexExtractPartnerData.exec(list[i]);

		if (results)
		{
			// remove white spaces and dots. If it's not a number, set it to 0 (not rated or closed)
			resultRating = results[3].replace(/\s/, '').replace(/\./, '');
			if (resultRating.length > 2)
			{
				if (resultRating.charAt(0) == 'C') // Closed
				{
					resultRating = -1;
				}
				else
				{
					resultRating = 0;
				}
			}
			else if (resultRating.length === 1 && resultRating !== 0 && resultRating !== '0')
			{
				resultRating = resultRating.concat(0);
			}
			re[i - 1] = new mfi(results[1], results[2], parseInt(resultRating, 10), false, false,
					'', 0, 0, 0);
		}
	}
	if (re.length !== iPartners)
	{
		console.log(re.length + ' / ' + iPartners);
	}
	else
	{
		console.log('Consistent (extracted / available): ' + re.length + ' / ' + iPartners);
	}
	return re;
}

function createCheckbox(resSorted, callback)
{
	if (!resSorted)
	{
		if (DEBUG > 0)
		{
			console.log('No res to create checkboxed!');
		}
		// return;
	}

	var trends_dom = document.getElementById('mfi_list');
	var hasFilter = false;

	for ( var i = 0, len = resSorted.length; i < len; i++)
	{
		var id = resSorted[i].id;
		var cellBlock = document.getElementById(id);
		var blocked = resSorted[i].blocked;
		var highlighted = resSorted[i].highlight;
		var comment = resSorted[i].cat;
		var top = resSorted[i].top;
		var sec = resSorted[i].religious;
		var soc = resSorted[i].social;

		if (cellBlock)
		{
			blocked = cellBlock.checked;
			highlighted = document.getElementById(id + 'd').checked;
			comment = document.getElementById(id + 'c').value;
			cellBlock.parentNode.parentNode.parentNode.removeChild(cellBlock.parentNode.parentNode);
		}

		cellBlock = document.createElement('input');
		cellBlock.type = 'checkbox';
		cellBlock.checked = blocked;
		cellBlock.id = id;

		var cellHighlight = document.createElement('input');
		cellHighlight.type = 'checkbox';
		cellHighlight.checked = highlighted;
		cellHighlight.id = id + 'd';

		var cellRating = document.createElement('span');
		if (resSorted[i].rating >= 0)
		{
			cellRating.setAttribute('class', 'rating-static rating-' + resSorted[i].rating);
			cellRating.setAttribute('title', resSorted[i].rating);
		}
		else
		{
			cellRating.setAttribute('class', 'rating-closed');
			cellRating.setAttribute('title', 'Closed');
		}

		var cellId = document.createTextNode(id);
		var cellName = document.createTextNode(resSorted[i].name.substring(0, 80));

		var cellComment = document.createElement('input');
		cellComment.type = 'text';
		cellComment.setAttribute('value', comment);
		cellComment.setAttribute('size', '30');
		cellComment.id = id + 'c';

		var tr = trends_dom.appendChild(document.createElement('tr'));
		var td1 = tr.appendChild(document.createElement('td'));
		var td2 = tr.appendChild(document.createElement('td'));
		var td3 = tr.appendChild(document.createElement('td'));
		var td3b = tr.appendChild(document.createElement('td'));
		var td3c = tr.appendChild(document.createElement('td'));
		var td4 = tr.appendChild(document.createElement('td'));
		var td5 = tr.appendChild(document.createElement('td'));
		var td6 = tr.appendChild(document.createElement('td'));
		var td7 = tr.appendChild(document.createElement('td'));

		td1.className = 'centered';
		td2.className = 'centered';
		td4.className = 'centered';
		td5.className = 'centered';

		td1.appendChild(cellBlock);
		td2.appendChild(cellHighlight);

		setTopAttribs(td3, top);
		setSecAttribs(td3b, sec);
		setSocAttribs(td3c, soc);

		td4.appendChild(cellRating);
		td5.appendChild(cellId);
		td6.appendChild(cellName);
		td7.appendChild(cellComment);

		cellBlock.addEventListener('change', updateItem, false);
		cellHighlight.addEventListener('change', updateItem, false);

		cellBlock.value = resSorted[i].name;
		cellBlock.name = resSorted[i].name;
		if (!hasFilter)
		{
			hasFilter = blocked || highlighted;
		}
		updateItemManually(cellBlock);
	}
	partnerCount.innerHTML = resSorted.length + ' Kiva Partners';
	var d = new Date();
	d.setTime(bg.mfiUpdateTimeStamp);
	partnerLastUpdate.innerHTML = 'Last updated: ' + d.toLocaleString();

	if (!hasFilter)
	{
		$('#status').html('No MFIs configured to be filtered or highlighted.');
		$('#status').error();
	}
	callback();
}

function setTopAttribs(item, id)
{
	switch (id)
	{
		case 0:
			item.setAttribute('class', 'score-top-none');
			item.setAttribute('title', 'No data');
			break;
		case 1:
			item.setAttribute('class', 'score-top-bottom');
			item.setAttribute('title', 'Highly religious');
			break;
		case 2:
			item.setAttribute('class', 'score-top-neutral');
			item.setAttribute('title', 'Religious');
			break;
		case 3:
			item.setAttribute('class', 'score-top-good');
			item.setAttribute('title', 'Limited/Non-Religious');
			break;
		case 4:
			item.setAttribute('class', 'score-top-top');
			item.setAttribute('title', 'Non-Religious and socialy active');
			break;
		default:
			item.setAttribute('class', 'score-top-neutral');
			item.setAttribute('title', 'No data / religious');
			break;
	}
}
function setSecAttribs(item, id)
{
	switch (id)
	{
		case 1:
			item.setAttribute('class', 'score-sec-bad');
			item.setAttribute('title', 'Religious');
			break;
		case 2:
			item.setAttribute('class', 'score-sec-bad');
			item.setAttribute('title', 'Religious');
			break;
		case 3:
			item.setAttribute('class', 'score-sec-good');
			item.setAttribute('title', 'Religious compounds');
			break;
		case 4:
			item.setAttribute('class', 'score-sec-top');
			item.setAttribute('title', 'Non-Religious');
			break;
		default:
			// 
			break;
	}
}
function setSocAttribs(item, id)
{
	var sClass = '';
	var sTitle = '';
	switch (id)
	{
		case 1:
			sClass = 'score-soc-bad';
			sTitle = 'No/few social activities';
			break;
		case 2:
			sClass = 'score-soc-bad';
			sTitle = 'No/few social activities';
			break;
		case 3:
			sClass = 'score-soc-ok';
			sTitle = 'Social activities';
			break;
		case 4:
			sClass = 'score-soc-top';
			sTitle = 'Comprehensive social activities';
			break;
		default:
			// 
			break;
	}
	item.setAttribute('class', sClass);
	item.setAttribute('title', sTitle);
}
function updateItemManually(item)
{
	if (DEBUG > 0)
	{
		console.log('Checkbox changed: ' + item.id);
	}
	var trs = item.parentNode.parentNode;
	var inputs = trs.getElementsByTagName('input');
	var cellBlock = inputs[0];
	var cellHighlight = inputs[1];

	// TODO use user configured colors
	trs.removeAttribute('class');

	if (!cellHighlight.checked && !cellBlock.checked)
	{
		return;
	}
	else if (cellHighlight.checked && cellBlock.checked)
	{
		trs.setAttribute('class', 'doubleChecked');
	}
	else if (cellBlock.checked)
	{
		trs.setAttribute('class', 'filteredChecked');
	}
	else if (cellHighlight.checked)
	{
		trs.setAttribute('class', 'highlightedChecked');
	}
}

function updateItem()
{
	updateItemManually(this);
}

function fetch(callback)
{
	$('#status').html('Fetching Field Partners...');
	$('#status').highlight();

	fetchPartners(function()
	{
		createCheckbox(res, function()
		{
			save_options(function()
			{
				callback();
			});
		});
	});
}

function fetchAaList(callback)
{
	$('#status').html('Fetching AASFSHNR MFI ratings...');
	$('#status').highlight();

	fetchAaData(function()
	{
		callback();
	});
}
function errorHighlight(e, type, icon)
{
	if (!icon)
	{
		if (type === 'highlight')
		{
			icon = 'ui-icon-info';
		}
		else
		{
			icon = 'ui-icon-alert';
		}
	}
	return e.each(function()
	{
		$(this).addClass('ui-widget');
		var h = '<div class="ui-state-' + type + ' ui-corner-all" style="padding:0 .7em;">';
		h += '<p>';
		h += '<span class="ui-icon ' + icon + '" style="float:left;margin-right: .3em;"></span>';
		h += $(this).text();
		h += '</p>';
		h += '</div>';

		$(this).html(h);
	});
}

// error dialog
(function($)
{
	$.fn.error = function()
	{
		errorHighlight(this, 'error');
	};
})(jQuery);

// highlight (alert) dialog
(function($)
{
	$.fn.highlight = function()
	{
		errorHighlight(this, 'highlight');
	};
})(jQuery);

/**
 * Resets (truncates) the DB with all MFI data and user settings
 */
function resetDb()
{
	storage.remove('mfi_list', function(items)
	{
		res = [];
	});
}

function importDb(data, callback)
{
	var tmp, tmpItem, gold = Object.keys(new mfi(0, '', 0, false, false, '', 0, 0, 0)).join('');
	try
	{
		tmp = JSON.parse(data);
	}
	catch (SyntaxError)
	{
		callback(false);
		return;
	}

	for ( var i = 0, l = tmp.length; i < l; i++)
	{
		tmpItem = tmp[i];
		if (tmpItem.name === undefined || Object.keys(tmpItem).join('') != gold)
		{
			callback(false);
			return;
		}
	}

	resetDb();
	document.getElementById('mfi_list').innerHTML = '';
	res = tmp;
	save_options(function()
	{
		callback(true);
	});

}

/**
 * Creates the link for the export / download of the DB
 */
function createDbExportLink()
{
	window.URL = window.webkitURL || window.URL;
	window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder;

	dbdlLink.download = 'db.json';
	dbdlLink.href = window.URL.createObjectURL(new Blob([ JSON.stringify(res) ], {
		type : 'text/plain'
	}));

	dbdlLink.dataset.downloadurl = [ 'text/plain', dbdlLink.download, dbdlLink.href ].join(':');
	dbdlLink.draggable = true;

	dbdlLink.onclick = function(e)
	{
		if ('disabled' in this.dataset)
		{
			return false;
		}
	};
}

/**
 * Close the options tab
 */
function close()
{
	chrome.tabs.getCurrent(function(tab)
	{
		chrome.tabs.remove(tab.id, function()
		{
			//
		});
	});
}

/* ----- LISTENERS ----- */

document.addEventListener('DOMContentLoaded', function()
{
	// because fetch can disable optionsAutoClose we have to keep the previous state
	var autoClose = bg.optionsAutoClose;

	restore_options(function()
	{
		// was intended to be automatically closed
		if (autoClose)
		{
			if (bg.optionsAutoClose)
			{
				bg.optionsAutoClose = false;
				fetch(function()
				{
					close();
				});
			}
			else
			{
				close();
			}
		}
		createDbExportLink();
	});
});

/* ----- END LISTENERS ----- */
